package com.bearingnavi.android.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

public class StateSaver {
	private static StateSaver instance;
	private String filename = com.bearingnavi.android.BearingNaviActivity.appDir+"/map-markers.bnv";
	private String marshalledData;
	private Logger log = Logger.getLogger(getClass());
	private MapView mapView;
	
	public static StateSaver getInstance() {
		return instance;
	}
	
	public static void createInstance(MapView mapView) {
		instance = new StateSaver(mapView);
	}
	
	private StateSaver(MapView mapView) {
		this.mapView = mapView;
		this.marshalledData = getFileContent(filename);
	}
	
	public void marshalOverlays(List<Overlay> overlays) {
		marshalledData="";
		for (Overlay overlay : overlays) {
			if (overlay instanceof MarshalOverlay) {
				String objectData = ((MarshalOverlay)overlay).marshal();
				if (objectData != null) {
					marshalledData += overlay.getClass().getName() + MarshalOverlay.FIELDS_SEPARATOR;
					marshalledData += objectData + MarshalOverlay.OBJECTS_SEPARATOR;
				}
			}
		}
		if(marshalledData.length() > 0) {
			marshalledData = marshalledData.substring(0, marshalledData.length()-MarshalOverlay.OBJECTS_SEPARATOR.length());
		}
		
		save();
	}
	
	public List<Overlay> getSavedOverlays() {
		if (marshalledData==null || marshalledData.length() == 0) {
			log.debug("No marshalled data found in file system.");
			return new ArrayList<Overlay>();
		}
		log.debug("marshalled data > "+marshalledData);
		
		return OverlayResolver.overlayFactory(marshalledData, true, mapView);
	}
	
	public void save() {
		try {
			FileWriter outFile = new FileWriter(filename, false);
			outFile.write(marshalledData);
			outFile.flush();
			outFile.close();
		} catch (IOException e) {
			log.error(e, e);
		}
	}
	
	public String getFileContent(String filename) {
		FileInputStream stream = null;
		try {
		
			stream = new FileInputStream(new File(filename));
			FileChannel fc = stream.getChannel();
			MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
			
			return Charset.defaultCharset().decode(bb).toString();
		} catch (IOException e){
			log.error(e, e);
			return null;
		} finally {
			try {
				if (stream != null) {
					stream.close();	
				}
			} catch (IOException e) {
				log.error(e, e);
			}
		}
	}
	
}
